﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;

namespace ProgNetComponents.Serialization
{
    public static class SerializationTools
    {
        static SerializationTools()
        {
            RegisterSerializer(typeof(int), null);
            RegisterSerializer(typeof(string), null);
            RegisterSerializer(typeof(decimal), null);
            RegisterSerializer(typeof(float), null);
            RegisterSerializer(typeof(bool), null);
            RegisterSerializer(typeof(double), null);
            RegisterSerializer(typeof(byte), null);
            RegisterSerializer(typeof(short), null);
            RegisterSerializer(typeof(IList), typeof(IListSerializer));
        }

        private static Dictionary<Type, Type> Serializers = new Dictionary<Type, Type>();

        public static void RegisterSerializer(Type type, Type serializerType)
        {
            Serializers[type] = serializerType;
        }

        public static ProgNetObjectSerializer GetSerializer(Type objectType)
        {
            ProgNetObjectSerializer serializer = null;
            if (objectType == null || objectType == typeof(object))
                return new ProgNetObjectSerializer();

            if (Serializers.ContainsKey(objectType))
            {
                if (Serializers[objectType] != null)
                    return (ProgNetObjectSerializer)Activator.CreateInstance(Serializers[objectType]);
                else
                    return null;
            }
            serializer = GetCustomSerializerForInterfaces(objectType);
            if (serializer != null)
                return serializer;
            return GetSerializer(objectType.BaseType);
        }
        
        //public static ProgNetObjectSerializer GetCustomSerializer(Type objectType)
        //{
        //    if (objectType == null || objectType == typeof(object))
        //        return null;
        //    if (Serializers.ContainsKey(objectType))
        //        return (ProgNetObjectSerializer)Activator.CreateInstance(Serializers[objectType]);
        //    return  GetCustomSerializer(objectType.BaseType);
        //}
        public static ProgNetObjectSerializer GetCustomSerializerForInterfaces(Type objectType)
        {
            if (objectType == null || objectType == typeof(object))
                return null;
            if (Serializers.ContainsKey(objectType))
                return (ProgNetObjectSerializer)Activator.CreateInstance(Serializers[objectType]);
            var interfaces = objectType.GetInterfaces();
            if (interfaces != null)
            {
                ProgNetObjectSerializer s = null;
                foreach (var i in interfaces)
                {
                    s = GetCustomSerializerForInterfaces(i);
                    if (s != null)
                        return s;
                }
            }
            return null;
        }
        public static object Deserialize(string xml)
        {
            object obj = null;
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);
                var elThis = doc.SelectSingleElement("this");
                if (elThis != null)
                {
                    string Type = elThis.GetAttributeValue("Type");
                    Type t = System.Type.GetType(Type);
                    if (t != null)
                    {
                        obj = Activator.CreateInstance(t);
                        var serializer = GetSerializer(t);
                        serializer.Deserialize(obj, xml);
                    }
                }
            }
            catch { }
            return obj;
        }
    }
}
